package net.zigin.nhi.could.waste.service.impl;

import cn.afterturn.easypoi.excel.entity.ExportParams;
import net.zigin.commons.util.AssertUtil;
import net.zigin.commons.util.ParamsMapUtil;
import net.zigin.commons.util.ReflectUtil;
import net.zigin.commons.util.StringUtil;
import net.zigin.nhi.could.waste.aop.LoginAspect;
import net.zigin.nhi.could.waste.dao.*;
import net.zigin.nhi.could.waste.dto.SysUserStaffDto;
import net.zigin.nhi.could.waste.exception.EpiCloudException;
import net.zigin.nhi.could.waste.model.SysUser;
import net.zigin.nhi.could.waste.model.SysUserHospital;
import net.zigin.nhi.could.waste.util.ExcelUtil;
import net.zigin.nhi.could.waste.vo.*;
import net.zigin.nhi.could.waste.dto.MaterialBaseDto;
import net.zigin.nhi.could.waste.model.MaterialRecord;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import net.zigin.nhi.could.waste.model.MaterialBase;
import net.zigin.nhi.could.waste.service.MaterialBaseService;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/*#################################################################*
# 说明:以下代码通过哲勤代码生成工具自动生成    
# 工具:GeneratorCode
# 作者:mgw1986                                                  
# 生成时间:2021-9-12 21:08:08                                               
##################################################################*/


/**
 * MaterialBase服务实现类
 *
 * @author mgw1986
 * @version V1.0
 * @ClassName: MaterialBaseServiceImpl
 * @date 2021-9-12 21:08:08
 */
@Service
public class MaterialBaseServiceImpl extends AbstractServiceImpl<MaterialBase, String> implements MaterialBaseService {
    @Autowired
    private MaterialBaseMapper materialBaseMapper;
    @Autowired
    private SysUserHospitalMapper sysUserHospitalMapper;
    @Autowired
    private MaterialRecordMapper materialRecordMapper;
    @Autowired
    private MaterialApplyMapper materialApplyMapper;

    @Override
    public BaseMapper<MaterialBase, String> getMapper() {
        return materialBaseMapper;
    }

    @Override
    public String saveOrUpdate(MaterialBaseDto materialBaseDto) {
        AssertUtil.isNull(materialBaseDto, "");
        TokenInfoBo tokenInfo = LoginAspect.getTokenInfo();
        materialBaseDto.setHospitalBaseId(sysUserHospitalMapper.getHospitalBaseIdBySysUserId(tokenInfo.getUserId()));
        // 新增时 如果编号已存在 则只修改库存
        if (!StringUtil.isNullOrEmpty(materialBaseDto.getCode()) && StringUtil.isNullOrEmpty(materialBaseDto.getId())) {
            MaterialBase exist = materialBaseMapper.getOneByCode(materialBaseDto.getCode());
            if (exist != null) {
                // 修改库存
                exist.setReserve(exist.getReserve() + materialBaseDto.getReserve());
                // 刷新最大库存
                exist.setReserveMax(Math.max(exist.getReserve(), exist.getReserveMax()));
                exist.setModifyUser(tokenInfo.getLoginName());
                exist.setModifyTime(new Date());
                materialBaseMapper.updateByPrimaryKeySelective(exist);
                // todo 生成入库记录
                inStorage(exist, materialBaseDto.getReserve());
                return exist.getId();
            }
        }
        if (StringUtil.isNullOrEmpty(materialBaseDto.getId())) {
            materialBaseDto.setId(StringUtil.get32UUID());
            materialBaseDto.setCreateUser(tokenInfo.getLoginName());
            materialBaseDto.setCreateTime(new Date());
            materialBaseDto.setModifyTime(new Date());
            materialBaseDto.setReserveMax(materialBaseDto.getReserveMax());
            materialBaseDto.setReserveMin(materialBaseDto.getReserveMin());
            MaterialBase materialBase = ReflectUtil.copyProperties(materialBaseDto, MaterialBase.class);
            materialBaseMapper.insert(materialBase);
            inStorage(materialBase, materialBaseDto.getReserve());
            return materialBase.getId();
        } else {
            materialBaseDto.setModifyUser(tokenInfo.getLoginName());
            materialBaseDto.setModifyTime(new Date());
            MaterialBase materialBase = ReflectUtil.copyProperties(materialBaseDto, MaterialBase.class);
            materialBaseMapper.updateByPrimaryKeySelective(materialBase);
            return materialBase.getId();
        }
    }

    @Override
    public List<MaterialBaseVo> getList(MaterialBaseDto materialBaseDto) {
        Map<String, Object> paramMap = getMaterialBaseParam(materialBaseDto);
        List<MaterialBase> materialBases;
        if (materialBaseDto.getIsPage()) {
            materialBases = materialBaseMapper.selectListByPage(paramMap);
        } else {
            materialBases = materialBaseMapper.selectListByCondition(paramMap);
        }
        if (materialBases.isEmpty()) {
            return new ArrayList<>();
        }
        return ReflectUtil.copyProperties(materialBases, MaterialBaseVo.class);
    }

    @Override
    public Integer getCount(MaterialBaseDto materialBaseDto) {
        Map<String, Object> paramMap = getMaterialBaseParam(materialBaseDto);
        return materialBaseMapper.selectCount(paramMap);
    }

    @Override
    public void exportList(MaterialBaseDto materialBaseDto, HttpServletResponse response) {
        List<MaterialBaseVo> list = materialBaseMapper.getListByIds(materialBaseDto.getIds());
        try {
            // 不带标题
            ExcelUtil.exportExcel(list, MaterialBaseVo.class, "耗材信息", new ExportParams(), response);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void importList(MultipartFile file) {
        TokenInfoBo tokenInfo = LoginAspect.getTokenInfo();
        String hospitalBaseId = sysUserHospitalMapper.getHospitalBaseIdBySysUserId(tokenInfo.getUserId());
        try {
            List<MaterialBaseVo> materialBaseVos = ExcelUtil.importExcel(file, 0, 1, MaterialBaseVo.class);
            // 新建 todo 生成记录 如果编码已存在 则更改库存数
            materialBaseVos.forEach(materialBaseVo -> {
                if (materialBaseVo.getReserve() == null) {
                    throw new EpiCloudException("信息不全！");
                }
                MaterialBase exist = materialBaseMapper.getOneByCode(materialBaseVo.getCode());
                if (exist != null) {
                    // 修改库存
                    exist.setReserve(exist.getReserve() + materialBaseVo.getReserve());
                    // 刷新最大库存
                    exist.setReserveMax(Math.max(exist.getReserve(), exist.getReserveMax()));
                    exist.setModifyUser(tokenInfo.getLoginName());
                    exist.setModifyTime(new Date());
                    materialBaseMapper.updateByPrimaryKeySelective(exist);
                    // todo 生成入库记录
                    inStorage(exist, materialBaseVo.getReserve());
                } else {
                    MaterialBase materialBase = ReflectUtil.copyProperties(materialBaseVo, MaterialBase.class);
                    materialBase.setId(StringUtil.get32UUID());
                    materialBase.setCreateTime(new Date());
                    materialBase.setCreateUser(tokenInfo.getLoginName());
                    materialBase.setHospitalBaseId(hospitalBaseId);
                    materialBaseMapper.insert(materialBase);
                    inStorage(materialBase, materialBaseVo.getReserve());
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void downloadTemplate(HttpServletResponse response) {
        try {
            ExcelUtil.exportExcel(new ArrayList<>(), MaterialBaseVo.class, "耗材信息", new ExportParams(), response);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public Boolean judgeRemove(String id) {
        // 有无申请记录
        Map<String, Object> paramMap = ParamsMapUtil.getInstance().addParam("materialBaseId", id);
        int applyCount = materialApplyMapper.selectCount(paramMap);
        // 库存是否为0
        MaterialBase materialBase = materialBaseMapper.selectByPrimaryKey(id);
        // 是否是新增
        List<MaterialRecordVo> recordVos = materialRecordMapper.getInfoListByMaterialBaseId(id);
        return (applyCount > 0 || (recordVos.size() > 1 && materialBase.getReserve() > 0));
    }

    @Override
    public void remove(String id) {
        // 逻辑删除
        materialBaseMapper.remove(id);
    }

    private Map<String, Object> getMaterialBaseParam(MaterialBaseDto materialBaseDto) {
        TokenInfoBo tokenInfo = LoginAspect.getTokenInfo();
        materialBaseDto.setHospitalBaseId(sysUserHospitalMapper.getHospitalBaseIdBySysUserId(tokenInfo.getUserId()));
        return ParamsMapUtil.getInstance()
                .addParam("hospitalBaseId", materialBaseDto.getHospitalBaseId())
                .addParam("model", materialBaseDto.getModel())
                .addParam("name", materialBaseDto.getName())
                .addParam("code", materialBaseDto.getCode())
                .addParam("pageSize", materialBaseDto.getPageSize())
                .addParam("pageIndex", materialBaseDto.getPageIndex());
    }

    private void inStorage(MaterialBase materialBase, int reserve) {
        MaterialRecord materialRecord = new MaterialRecord(materialBase);
        // todo 数量 change before after
        materialRecord.setChangeNum(reserve);
        materialRecord.setBeforeNum(materialBase.getReserve() - reserve);
        materialRecord.setAfterNum(materialBase.getReserve());
        materialRecordMapper.insert(materialRecord);
    }
}